﻿using Mapster;
using Raffles.OA.Data;
using Raffles.OA.Data.Dto.Sale;
using Raffles.OA.Data.Entity.Sale;
using Raffles.OA.Service;
using Raffles.OA.Utility;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace Raffles.OA.WebApp.Areas.Sale.Controllers
{
    public class ProjectController : BaseController<ProjectEntity>
    {
        private UserService _userService;

        public ProjectController()
        {
            _userService = new UserService();
        }

        #region 视图

        /// <summary>
        /// 报价单
        /// </summary>
        /// <returns></returns>
        public ActionResult QuotationForm()
        {
            return View();
        }

        /// <summary>
        /// 报价单项明细
        /// </summary>
        /// <returns></returns>
        public ActionResult QuotationItemDetailForm()
        {
            return View();
        }

        /// <summary>
        /// 报价单打印
        /// </summary>
        /// <returns></returns>
        public ActionResult QuotationPrint()
        {
            return View();
        }

        /// <summary>
        /// 财务结算
        /// </summary>
        /// <returns></returns>
        public ActionResult FinanceSettlement()
        {
            return View();
        }

        /// <summary>
        /// 团组看板
        /// </summary>
        /// <returns></returns>
        public ActionResult DashBoard()
        {
            return View();
        }

        /// <summary>
        /// 交通导游成本明细
        /// </summary>
        /// <returns></returns>
        public ActionResult QuotationTransportDetailForm()
        {
            return View();
        }

        /// <summary>
        /// 团组培训成本明细
        /// </summary>
        /// <returns></returns>
        public ActionResult QuotationActivityDetailForm()
        {
            return View();
        }

        #endregion 视图

        /// <summary>
        /// 获取分页列表
        /// </summary>
        /// <param name="param"></param>
        /// <param name="pagination"></param>
        /// <returns></returns>
        public async Task<ActionResult> GetPageListJson(ProjectSearchParam param, Pagination pagination)
        {
            RefAsync<int> totalCount = 0;
            List<OrderByModel> orderList = OrderByModel.Create(
            new OrderByModel() { FieldName = pagination.Sort, OrderByType = pagination.SortType.ToUpper() == "ASC" ? OrderByType.Asc : OrderByType.Desc }
            );
            var datas = await _dbContext.Queryable<ProjectEntity>()
                                .Where(x => x.FormType == ProjectFormEnum.CustomerSettlement.ToString())
                                .WhereIF(OperatorProvider.Provider.GetCurrent().DataScope == (int)DataScopeEnum.SELF, x => x.SaleManagerId == OperatorProvider.Provider.GetCurrent().Id || x.InvolveId.Contains(OperatorProvider.Provider.GetCurrent().Id.ToString()))//看到自己和自己参与的
                                .WhereIF(!param.KeyWord.IsEmpty(), x => x.Code.Contains(param.KeyWord) || x.ContractCode.Contains(param.KeyWord) || x.Name.Contains(param.KeyWord) || x.CustomerName.Contains(param.KeyWord))
                                .WhereIF(!param.Status.IsEmpty(), x => x.Status == param.Status)
                                .WhereIF(!param.DepartureDateStart.IsEmpty(), x => x.DepartureDate >= param.DepartureDateStart && x.DepartureDate <= param.DepartureDateEnd)
                                .WhereIF(!param.SalerId.IsEmpty(), x => x.SaleManagerId == param.SalerId)
                                .OrderBy(orderList)
                                .ToPageListAsync(pagination.PageIndex, pagination.PageSize, totalCount);
            return Content(DataResult<List<ProjectEntity>>.PageResult(datas, totalCount).ToJson());
        }

        /// <summary>
        /// 获取成本结算
        /// </summary>
        /// <param name="param"></param>
        /// <param name="pagination"></param>
        /// <returns></returns>
        public async Task<ActionResult> GetPageDetailListJson(int projectId)
        {
            List<ProjectEntity> datas = await _dbContext.Queryable<ProjectEntity>()
                                                        .Where(x => x.ParentId == projectId)
                                                        .OrderBy(x => x.DepartureDate)
                                                        .ToListAsync();
            return Content(DataResult<List<ProjectEntity>>.Success(datas).ToJson());
        }

        /// <summary>
        /// 获取项目参与人员(排除自己)
        /// </summary>
        /// <returns></returns>
        public async Task<ActionResult> GetInvolveSelect()
        {
            List<Dictionary<string, object>> dic = await _userService.GetSalerSelectList(null);
            dic = dic.Where(x => x["Key"].ToString() != OperatorProvider.Provider.GetCurrent().Id.ToString()).ToList();
            //dic.Remove(dic.Where(x => x["Id"].ToString() == OperatorProvider.Provider.GetCurrent().Id.ToString()).FirstOrDefault());
            return Content(DataResult<List<Dictionary<string, object>>>.Success(dic).ToJson());
        }

        /// <summary>
        /// 获取销售人员
        /// </summary>
        /// <returns></returns>
        public async Task<ActionResult> GetSalerSelect()
        {
            List<Dictionary<string, object>> dic = await _userService.GetSalerSelectList(null);
            return Content(DataResult<List<Dictionary<string, object>>>.Success(dic).ToJson());
        }

        /// <summary>
        /// 根据客户结算单获取所有成本结算单Id/Segment
        /// </summary>
        /// <returns></returns>
        public async Task<ActionResult> GetSettlementSegment(int projectId)
        {
            List<Dictionary<string, object>> dic = await _dbContext.Queryable<ProjectEntity>()
                                                                   .Where(x => x.ParentId == projectId)
                                                                   .Select(x => new { Key = x.Id, Value = x.CountrySegmentCN }).ToDictionaryListAsync();
            return Content(DataResult<List<Dictionary<string, object>>>.Success(dic).ToJson());
        }

        /// <summary>
        /// 保存销售报价单
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ActionResult> SaveQuotationForm(ProjectDto projectDto)
        {
            try
            {

                await _dbContext.BeginTranAsync();

                #region 前置校验
                //if (projectDto.QuotationItemList.Count > 0)
                //{ 
                //    var segment = await _dbContext.Queryable<BaseDestinationEntity>().Where(x => !x.DeletedMark && x.EnabledMark && x.ParentId == 0).ToListAsync();
                //    //各报价项是否存在同一分段选择重复项
                //    var list = projectDto.QuotationItemList.Where(x=>x.ItemId!=null)
                //                                           .GroupBy(x => new { x.QuotationItemCode, x.SegmentId,x.ItemId })
                //                                           .Where(x => x.Count() > 1)//分组后重复的
                //                                           .Select(x => new
                //                                           {
                //                                               QuotationItemName = EnumHelper.GetEnumDesc(typeof(QuotationItemEnum), CultureInfo.CurrentCulture.TextInfo.ToTitleCase(x.Key.QuotationItemCode)),
                //                                               SegmentId = x.Key.SegmentId,
                //                                               SegmentName = segment.FirstOrDefault(y => y.Id == x.Key.SegmentId)?.Name
                //                                           }).ToList();
                //    List<ValidateResult> results = new List<ValidateResult>();
                //    StringBuilder errorMsg = new StringBuilder();
                //    if (list.Count > 0)
                //    {
                //        foreach (var item in projectDto.CountrySegment.Where(x => list.Where(y => y.SegmentId == x).Any()))
                //        {
                //            errorMsg.Append($"【<span class='text-red text-bold'>{list.FirstOrDefault(x => x.SegmentId == item)?.SegmentName}段</span>】重复项:");
                //            errorMsg.AppendLine("<br/>");
                //            errorMsg.Append($"{string.Join(",", list.Where(x => x.SegmentId == item).Select(x => x.QuotationItemName).ToArray())}");
                //            errorMsg.AppendLine("<br/>");
                //        }
                //        return Json(DataResult<List<ValidateResult>>.Error(errorMsg.ToString()));
                //    } 
                //}

                if (projectDto.CountrySegment.Count() != projectDto.TripItemList.GroupBy(x => x.SegmentId).Count())
                {
                    return Json(DataResult.Error("分段安排填写不完整！"));
                }
                #endregion 前置校验
                 
                #region 表头信息

                ProjectEntity projectEntity = new ProjectEntity();
                DateTime? originDepartureDate = null;
                if (!projectDto.Id.IsNullOrZero())
                {
                    projectEntity = await _dbContext.Queryable<ProjectEntity>().InSingleAsync(projectDto.Id);
                    originDepartureDate = projectEntity.DepartureDate;
                }
                else
                {
                    //项目状态-数据录入
                    projectEntity.Status = (int)ProjectStatusEnum.DataIn;
                    projectEntity.CreatedBy = projectEntity.UpdatedBy = OperatorProvider.Provider.GetCurrent().Id;
                    projectEntity.Color = OperatorProvider.Provider.GetCurrent().Color ?? "bg-black";
                    projectEntity.OperateRate = OperatorProvider.Provider.GetCurrent().OperateRate;
                }
                projectDto.Adapt(projectEntity);
                //行程分段
                projectEntity.CountrySegment = string.Join(",", projectDto.CountrySegment.ToArray());
                var dataSegments = await _dbContext.Queryable<BaseDestinationEntity>().Where(x => projectDto.CountrySegment.Contains(x.Id)).Select(x => x.Name).ToArrayAsync();
                projectEntity.CountrySegmentCN = string.Join(",", dataSegments);
                //报价类目
                projectEntity.QuotationItemCode = string.Join(",", projectDto.QuotationItemCode.ToArray());
                //参与人员
                projectEntity.InvolveId = string.Join(",", projectDto.InvolveId.ToArray());
                var dataInvoles = await _dbContext.Queryable<User>().Where(x => projectDto.InvolveId.Contains(x.Id)).Select(x => x.RealName).ToArrayAsync();
                projectEntity.InvolveCN = string.Join(",", dataInvoles);
                //销售顾问
                projectEntity.SaleManagerId = OperatorProvider.Provider.GetCurrent().Id;
                projectEntity.SaleManagerName = OperatorProvider.Provider.GetCurrent().RealName;
                if (projectDto.FormType == ProjectFormEnum.CustomerSettlement.ToString())
                {
                    //团费税前结算货币
                    projectEntity.SaleSGDAmountBeforeTax = Math.Floor(projectDto.TotalSGDBeforeTax.Replace("$", "").ToDecimal());
                    //团费税前人民币
                    projectEntity.SaleRMBAmountBeforeTax = Math.Floor(projectDto.TotalRMBBeforeTax.Replace("￥", "").Replace("¥", "").ToDecimal());
                    //人均税前人民币
                    projectEntity.AverageSaleRMBAmountBeforeTax = Math.Floor(projectDto.AverageRMBBeforeTax.Replace("￥", "").Replace("¥", "").ToDecimal());
                    //团费税后结算货币
                    projectEntity.SaleSGDAmountAfterTax = Math.Floor(projectEntity.SaleSGDAmountBeforeTax.ToDecimal() + projectEntity.SaleSGDAmountBeforeTax.ToDecimal() * projectEntity.TaxRate.ToDecimal() * 0.01m);
                    //团费税后人民币
                    projectEntity.SaleRMBAmountAfterTax = Math.Floor(projectEntity.SaleRMBAmountBeforeTax.ToDecimal() + projectEntity.SaleRMBAmountBeforeTax.ToDecimal() * projectEntity.TaxRate.ToDecimal() * 0.01m);
                    //人均税后人民币
                    projectEntity.AverageSaleRMBAmountAfterTax = Math.Floor(projectEntity.AverageSaleRMBAmountBeforeTax.ToDecimal() + projectEntity.AverageSaleRMBAmountBeforeTax.ToDecimal() * projectEntity.TaxRate.ToDecimal() * 0.01m);
                }
                else
                {
                    //编辑成本结算单时，赋值在成本字段上
                    //团费税前结算货币
                    projectEntity.CostSGDAmountBeforeTax = Math.Floor(projectDto.TotalSGDBeforeTax.Replace("$", "").ToDecimal());
                    //团费税前人民币
                    projectEntity.CostRMBAmountBeforeTax = Math.Floor(projectDto.TotalRMBBeforeTax.Replace("￥", "").Replace("¥", "").ToDecimal());
                    //团费税后结算货币
                    projectEntity.CostSGDAmountAfterTax = Math.Floor(projectEntity.CostSGDAmountBeforeTax.ToDecimal() + projectEntity.CostSGDAmountBeforeTax.ToDecimal() * projectEntity.TaxRate.ToDecimal() * 0.01m);
                    //团费税后人民币
                    projectEntity.CostRMBAmountAfterTax = Math.Floor(projectEntity.CostRMBAmountBeforeTax.ToDecimal() + projectEntity.CostRMBAmountBeforeTax.ToDecimal() * projectEntity.TaxRate.ToDecimal() * 0.01m);
                    //成本支付的初始状态
                    projectEntity.PayStatus = (int)ProjectCostPayEnum.NotPay;
                }
                if (projectDto.Id.IsNullOrZero())
                {
                    //新增时,生成项目编号
                    projectEntity.Code = GetNumberCode(projectDto.DepartureDate.ToDate());
                    await _dbContext.Insertable<ProjectEntity>(projectEntity).ExecuteCommandIdentityIntoEntityAsync();
                }
                else
                {
                    //编辑时，出行日期改变了，则重新生成项目编号
                    if (originDepartureDate != null && projectEntity.DepartureDate != originDepartureDate)
                    {
                        projectEntity.Code = GetNumberCode(projectDto.DepartureDate.ToDate());
                    }
                    projectEntity.UpdatedBy = OperatorProvider.Provider.GetCurrent().Id;
                    projectEntity.UpdatedOn = DateTime.Now;
                    await _dbContext.Updateable<ProjectEntity>(projectEntity).ExecuteCommandAsync();
                }

                #endregion 表头信息

                #region 编辑时清空表体

                if (!projectDto.Id.IsNullOrZero())
                {
                    #region 成本结算(编辑客户报价单时)

                    if (projectDto.FormType == ProjectFormEnum.CustomerSettlement.ToString())
                    {
                        //清空分段成本结算相关,先删除表体
                        var projectSettlements = await _dbContext.Queryable<ProjectEntity>().Where(x => x.ParentId == projectEntity.Id).ToListAsync();
                        foreach (var item in projectSettlements)
                        {
                            //清空行程天数
                            await _dbContext.Deleteable<ProjectQuotationTripEntity>().Where(x => x.ProjectId == item.Id).ExecuteCommandAsync();
                            //清空行程安排和明细
                            await _dbContext.Deleteable<ProjectQuotationItemEntity>().Where(x => x.ProjectId == item.Id).ExecuteCommandAsync();
                            await _dbContext.Deleteable<ProjectQuotationItemDetailEntity>().Where(x => x.ProjectId == item.Id).ExecuteCommandAsync();
                            await _dbContext.Deleteable<ProjectQuotationTransportDetailEntity>().Where(x => x.ProjectId == item.Id).ExecuteCommandAsync();
                            await _dbContext.Deleteable<ProjectQuotationActivityDetailEntity>().Where(x => x.ProjectId == item.Id).ExecuteCommandAsync();
                            //清空付款信息
                            await _dbContext.Deleteable<ProjectPaymentEntity>().Where(x => x.ProjectId == item.Id).ExecuteCommandAsync();
                        }
                        //后删除表头
                        await _dbContext.Deleteable<ProjectEntity>().Where(x => x.ParentId == projectEntity.Id).ExecuteCommandAsync();
                    }

                    #endregion 成本结算(编辑客户报价单时)

                    #region 行程天数

                    //清空行程天数
                    await _dbContext.Deleteable<ProjectQuotationTripEntity>().Where(x => x.ProjectId == projectEntity.Id).ExecuteCommandAsync();

                    #endregion 行程天数

                    #region 行程安排

                    //清空行程安排和明细
                    await _dbContext.Deleteable<ProjectQuotationItemEntity>().Where(x => x.ProjectId == projectEntity.Id).ExecuteCommandAsync();
                    await _dbContext.Deleteable<ProjectQuotationItemDetailEntity>().Where(x => x.ProjectId == projectEntity.Id).ExecuteCommandAsync();
                    await _dbContext.Deleteable<ProjectQuotationTransportDetailEntity>().Where(x => x.ProjectId == projectEntity.Id).ExecuteCommandAsync();
                    await _dbContext.Deleteable<ProjectQuotationActivityDetailEntity>().Where(x => x.ProjectId == projectEntity.Id).ExecuteCommandAsync();

                    #endregion 行程安排

                    #region 付款信息

                    //清空付款信息
                    await _dbContext.Deleteable<ProjectPaymentEntity>().Where(x => x.ProjectId == projectEntity.Id).ExecuteCommandAsync();

                    #endregion 付款信息

                    #region 运营成本

                    //清空运营成本
                    await _dbContext.Deleteable<ProjectOperateCostEntity>().Where(x => x.ProjectId == projectEntity.Id).ExecuteCommandAsync();

                    #endregion 运营成本
                }

                #endregion 编辑时清空表体

                #region 关联生成成本结算信息(新增客户报价单时)

                if (projectDto.FormType == ProjectFormEnum.CustomerSettlement.ToString())
                {
                    int serialNo = 1;
                    foreach (var segment in projectDto.CountrySegment)
                    {
                        ProjectEntity projectSettlementEntity = new ProjectEntity();

                        #region 表头信息

                        projectEntity.Adapt(projectSettlementEntity);
                        //成本结算默认以人民币结算，相应汇率=1,税率=0(暂时注释,从报价单带出)
                        //projectSettlementEntity.SettlementCurrency = "RMB";
                        //projectSettlementEntity.SettlementCurrencyCN = "人民币";
                        //projectSettlementEntity.SettlementRate = projectSettlementEntity.PaymentRate = 1;
                        projectSettlementEntity.TaxRate = 0;
                        projectSettlementEntity.FormType = ProjectFormEnum.FinanceSettlement.ToString();
                        projectSettlementEntity.ParentId = projectEntity.Id;
                        //项目编号
                        projectSettlementEntity.Code = $"{projectEntity.Code}-{serialNo}";
                        //行程分段
                        projectSettlementEntity.CountrySegment = segment.ToString();
                        projectSettlementEntity.CountrySegmentCN = (await _dbContext.Queryable<BaseDestinationEntity>().InSingleAsync(segment))?.Name;
                        //以下两个实体赋值 因为设置了Adapt忽略 所以手动进行再次赋值
                        projectSettlementEntity.QuotationItemCode = projectEntity.QuotationItemCode;
                        projectSettlementEntity.InvolveId = projectEntity.InvolveId;

                        #region 拆分计算出分段销售报价，赋值在销售字段上

                        //税前SGD 用于其余字段的换算
                        var saleSGDTotal = projectDto.QuotationItemList.Where(x => x.SegmentId == segment).Sum(x => x.Total).ToDecimal();
                        //团费税前新币
                        projectSettlementEntity.SaleSGDAmountBeforeTax = Math.Floor(saleSGDTotal);
                        //团费税前人民币
                        projectSettlementEntity.SaleRMBAmountBeforeTax = Math.Floor(saleSGDTotal * projectEntity.SettlementRate.ToDecimal());
                        //人均税前人民币
                        projectSettlementEntity.AverageSaleRMBAmountBeforeTax = Math.Floor(saleSGDTotal * projectEntity.SettlementRate.ToDecimal() / projectEntity.AdultTotal);
                        //团费税后新币
                        projectSettlementEntity.SaleSGDAmountAfterTax = Math.Floor(projectSettlementEntity.SaleSGDAmountBeforeTax.ToDecimal() + projectSettlementEntity.SaleSGDAmountBeforeTax.ToDecimal() * projectEntity.TaxRate.ToDecimal() * 0.01m);
                        //团费税后人民币
                        projectSettlementEntity.SaleRMBAmountAfterTax = Math.Floor(projectSettlementEntity.SaleRMBAmountBeforeTax.ToDecimal() + projectSettlementEntity.SaleRMBAmountBeforeTax.ToDecimal() * projectEntity.TaxRate.ToDecimal() * 0.01m); ;
                        //人均税后人民币
                        projectSettlementEntity.AverageSaleRMBAmountAfterTax = Math.Floor(projectSettlementEntity.AverageSaleRMBAmountBeforeTax.ToDecimal() + projectSettlementEntity.AverageSaleRMBAmountBeforeTax.ToDecimal() * projectEntity.TaxRate.ToDecimal() * 0.01m); ;

                        #endregion 拆分计算出分段销售报价，赋值在销售字段上

                        projectSettlementEntity.CostSGDAmountBeforeTax = 0;
                        projectSettlementEntity.CostRMBAmountBeforeTax = 0;
                        projectSettlementEntity.CostSGDAmountAfterTax = 0;
                        projectSettlementEntity.CostRMBAmountAfterTax = 0;
                        //行程日期
                        var data = projectDto.TripItemList.Where(x => x.SegmentId == segment).ToList();
                        projectSettlementEntity.DepartureDate = data.OrderBy(x => x.TripDate).FirstOrDefault()?.TripDate;
                        projectSettlementEntity.ReturnDate = data.OrderByDescending(x => x.TripDate).FirstOrDefault()?.TripDate;
                        if (projectSettlementEntity.DepartureDate != null && projectSettlementEntity.ReturnDate != null)
                        {
                            projectSettlementEntity.DayTotal = (projectSettlementEntity.ReturnDate.ToDate() - projectSettlementEntity.DepartureDate.ToDate()).Days + 1;
                        }

                        projectSettlementEntity.PayStatus = (int)ProjectCostPayEnum.NotPay;

                        await _dbContext.Insertable<ProjectEntity>(projectSettlementEntity).ExecuteCommandIdentityIntoEntityAsync();

                        #endregion 表头信息

                        #region 行程天数

                        List<ProjectQuotationTripEntity> tripSettlementEntitys = new List<ProjectQuotationTripEntity>();
                        foreach (var itemTripSettlement in projectDto.TripItemList.Where(x => x.SegmentId == segment))
                        {
                            ProjectQuotationTripEntity tripSettlementEntity = new ProjectQuotationTripEntity();
                            itemTripSettlement.Adapt(tripSettlementEntity);
                            tripSettlementEntity.ProjectId = projectSettlementEntity.Id;
                            tripSettlementEntity.TripPlaceId = string.Join(",", itemTripSettlement.TripPlaceId.ToArray());
                            tripSettlementEntity.TripPlaceName = string.Join(",", itemTripSettlement.TripPlaceName.ToArray());
                            tripSettlementEntitys.Add(tripSettlementEntity);
                        }
                        await _dbContext.Insertable<ProjectQuotationTripEntity>(tripSettlementEntitys).ExecuteCommandAsync();

                        #endregion 行程天数

                        #region 行程安排

                        List<ProjectQuotationItemEntity> projectSettlementQuotationItems = new List<ProjectQuotationItemEntity>();
                        List<ProjectQuotationActivityDetailEntity> projectQuotationActivityDetails = new List<ProjectQuotationActivityDetailEntity>();
                        foreach (var itemQuotation in projectDto.QuotationItemList.Where(x => x.SegmentId == segment))
                        {
                            ProjectQuotationItemEntity quotationItem = new ProjectQuotationItemEntity();
                            itemQuotation.Adapt(quotationItem);
                            quotationItem.ProjectId = projectSettlementEntity.Id;
                            quotationItem.Price = quotationItem.Total = null;
                            quotationItem.SalePrice = itemQuotation.Price;//销售单价
                            quotationItem.SaleTotal = itemQuotation.Total;//销售总价
                            quotationItem.QuotationItemCode = itemQuotation.QuotationItemCode.Remove(1).ToUpper() + itemQuotation.QuotationItemCode.Substring(1);

                            if (itemQuotation.QuotationItemCode.ToLower() == QuotationItemEnum.GroupActivity.ToString().ToLower())
                            {
                                await _dbContext.Insertable<ProjectQuotationItemEntity>(quotationItem).ExecuteCommandIdentityIntoEntityAsync();
                                //以下是需要带出报价单团组培训报价明细项作为团组的利润核算
                                projectQuotationActivityDetails.AddRange(itemQuotation.ActivityDetail.Select(x => new ProjectQuotationActivityDetailEntity
                                {
                                    ProjectId = projectSettlementEntity.Id,
                                    QuotationItemId = quotationItem.Id,
                                    Name = null,
                                    ItemName = x.ItemName,
                                    ItemCostName = null,
                                    ItemCostPrice = null,
                                    ItemSalePrice = x.ItemSalePrice,
                                    ItemQty = x.ItemQty,
                                    Mark = x.Mark
                                }));
                                if (itemQuotation.ItemId > 0)
                                { 
                                    //这里表示只有资源中心带出的才需要追加其他选项，手工输入的不需要
                                    //初始化时,追加一个其他选项
                                    projectQuotationActivityDetails.Add(new ProjectQuotationActivityDetailEntity
                                    {
                                        ProjectId = projectSettlementEntity.Id,
                                        QuotationItemId = quotationItem.Id,
                                        Name = null,
                                        ItemName = "其他",
                                        ItemCostName = null,
                                        ItemCostPrice = null,
                                        ItemSalePrice = null,
                                        ItemQty = 1,
                                        Mark = false
                                    });
                                }
                            }
                            else
                            {
                                //需要根据QuotationItemCode和SegmentId组合匹配
                                projectDto.QuotationItemList.FirstOrDefault(x => x.QuotationItemCode == itemQuotation.QuotationItemCode && x.SegmentId == itemQuotation.SegmentId && x.ItemId == itemQuotation.ItemId).Adapt(quotationItem);
                                quotationItem.ProjectId = projectSettlementEntity.Id;
                                quotationItem.Price = quotationItem.Total = null;
                                quotationItem.SalePrice = itemQuotation.Price;//销售单价
                                quotationItem.SaleTotal = itemQuotation.Total;//销售总价
                                quotationItem.QuotationItemCode = itemQuotation.QuotationItemCode.Remove(1).ToUpper() + itemQuotation.QuotationItemCode.Substring(1);
                                projectSettlementQuotationItems.Add(quotationItem);
                            }
                        }
                        if (projectQuotationActivityDetails.Count > 0)
                        {
                            await _dbContext.Insertable<ProjectQuotationActivityDetailEntity>(projectQuotationActivityDetails).ExecuteCommandAsync();
                        }
                        if (projectSettlementQuotationItems.Count > 0)
                        {
                            await _dbContext.Insertable<ProjectQuotationItemEntity>(projectSettlementQuotationItems).ExecuteCommandAsync();
                        }

                        #endregion 行程安排

                        serialNo++;
                    }
                }

                #endregion 关联生成成本结算信息(新增客户报价单时)

                #region 行程天数

                List<ProjectQuotationTripEntity> tripEntitys = new List<ProjectQuotationTripEntity>();
                foreach (var item in projectDto.TripItemList)
                {
                    ProjectQuotationTripEntity tripEntity = new ProjectQuotationTripEntity();
                    item.Adapt(tripEntity);
                    tripEntity.ProjectId = projectEntity.Id;
                    tripEntity.TripPlaceId = string.Join(",", item.TripPlaceId.ToArray());
                    tripEntity.TripPlaceName = string.Join(",", item.TripPlaceName.ToArray());
                    tripEntitys.Add(tripEntity);
                }
                await _dbContext.Insertable<ProjectQuotationTripEntity>(tripEntitys).ExecuteCommandAsync();

                #endregion 行程天数

                #region 行程安排

                foreach (var segment in projectDto.CountrySegment)
                {
                    List<ProjectQuotationItemEntity> projectQuotationItems = new List<ProjectQuotationItemEntity>();
                    List<ProjectQuotationTransportDetailEntity> projectQuotationTransportDetails = new List<ProjectQuotationTransportDetailEntity>();
                    List<ProjectQuotationActivityDetailEntity> projectQuotationActivityDetails = new List<ProjectQuotationActivityDetailEntity>();
                    
                    foreach (var item in projectDto.QuotationItemList.Where(x => x.SegmentId == segment))
                    {
                        ProjectQuotationItemEntity quotationItem = new ProjectQuotationItemEntity();
                        item.Adapt(quotationItem);
                        quotationItem.ProjectId = projectEntity.Id;
                        quotationItem.QuotationItemCode = item.QuotationItemCode.Remove(1).ToUpper() + item.QuotationItemCode.Substring(1);

                        if (item.QuotationItemCode.ToLower() == QuotationItemEnum.GroupActivity.ToString().ToLower())
                        {
                            await _dbContext.Insertable<ProjectQuotationItemEntity>(quotationItem).ExecuteCommandIdentityIntoEntityAsync();
                            if (projectDto.FormType == ProjectFormEnum.CustomerSettlement.ToString())
                            {
                                projectQuotationActivityDetails.AddRange(item.ActivityDetail.Select(x => new ProjectQuotationActivityDetailEntity
                                {
                                    ProjectId = projectEntity.Id,
                                    QuotationItemId = quotationItem.Id,
                                    Name = x.Name,
                                    ItemName = x.ItemName,
                                    ItemCostPrice = x.ItemCostPrice,
                                    ItemSalePrice = x.ItemSalePrice,
                                    ItemQty = x.ItemQty,
                                    Mark = x.Mark
                                }));
                            }
                            else
                            {
                                projectQuotationActivityDetails.AddRange(item.ActivityDetail.Select(x => new ProjectQuotationActivityDetailEntity
                                {
                                    ProjectId = projectEntity.Id,
                                    QuotationItemId = quotationItem.Id,
                                    Name = null,
                                    ItemName = x.ItemName,
                                    ItemCostName = x.ItemCostName,
                                    ItemCostPrice = x.ItemCostPrice,
                                    ItemSalePrice = x.ItemSalePrice,
                                    ItemQty = x.ItemQty,
                                    Mark = x.Mark
                                }));
                            }
                        }
                        else if (item.QuotationItemCode.ToLower() == QuotationItemEnum.Transportation.ToString().ToLower())
                        {
                            await _dbContext.Insertable<ProjectQuotationItemEntity>(quotationItem).ExecuteCommandIdentityIntoEntityAsync();
                            projectQuotationTransportDetails.AddRange(item.TransportDetail.Select(x => new ProjectQuotationTransportDetailEntity
                            {
                                ProjectId = projectEntity.Id,
                                QuotationItemId = quotationItem.Id,
                                Day = x.Day,
                                UseTime = x.UseTime,
                                PlanHour = x.PlanHour,
                                OverTime = x.OverTime,
                                ServiceFee = x.ServiceFee,
                                SalaryFee = x.SalaryFee,
                                OverTimeFee = x.OverTimeFee,
                                TotalFee = x.TotalFee
                            }));
                        }
                        else
                        {
                            var data = projectDto.QuotationItemList.FirstOrDefault(x => x.QuotationItemCode == item.QuotationItemCode && x.SegmentId == item.SegmentId && x.ItemId == item.ItemId);
                            //需要根据QuotationItemCode和SegmentId组合匹配
                            projectDto.QuotationItemList.FirstOrDefault(x => x.QuotationItemCode == item.QuotationItemCode && x.SegmentId == item.SegmentId && x.ItemId == item.ItemId).Adapt(quotationItem);
                            quotationItem.ProjectId = projectEntity.Id;
                            quotationItem.QuotationItemCode = item.QuotationItemCode.Remove(1).ToUpper() + item.QuotationItemCode.Substring(1);
                            projectQuotationItems.Add(quotationItem);
                        } 
                    }
                    if (projectQuotationTransportDetails.Count > 0)
                    {
                        await _dbContext.Insertable<ProjectQuotationTransportDetailEntity>(projectQuotationTransportDetails).ExecuteCommandAsync();
                    }

                    if (projectQuotationActivityDetails.Count > 0)
                    {
                        await _dbContext.Insertable<ProjectQuotationActivityDetailEntity>(projectQuotationActivityDetails).ExecuteCommandAsync();
                    }

                    if (projectQuotationItems.Count > 0)
                    {
                        await _dbContext.Insertable<ProjectQuotationItemEntity>(projectQuotationItems).ExecuteCommandAsync();
                    }
                }

                #endregion 行程安排

                #region 付款信息

                if (projectDto.FormType == ProjectFormEnum.CustomerSettlement.ToString())
                {
                    //清空付款信息
                    await _dbContext.Deleteable<ProjectPaymentEntity>().Where(x => x.ProjectId == projectEntity.Id).ExecuteCommandAsync();

                    List<ProjectPaymentEntity> paymentEntitys = projectDto.PayMoneyList.Select(x => new ProjectPaymentEntity
                    {
                        ProjectId = projectEntity.Id,
                        PaymentType = x.PayType,
                        Ratio = x.PayRate,
                        AmountSGD = x.PaySGD,
                        AmountRMB = x.PayRMB,
                        AmountOn = x.PayDate
                    }).ToList();
                    await _dbContext.Insertable<ProjectPaymentEntity>(paymentEntitys).ExecuteCommandAsync();
                }

                #endregion 付款信息

                #region 计算成本合计(编辑时)

                ProjectEntity parentEntity = new ProjectEntity();
                if (!projectDto.Id.IsNullOrZero())
                {
                    //如果编辑的是财务结算单，则需要更新客户结算单的销售成本
                    if (projectDto.FormType == ProjectFormEnum.FinanceSettlement.ToString())
                    {
                        parentEntity = await _dbContext.Queryable<ProjectEntity>().InSingleAsync(projectEntity.ParentId);
                    }
                    else
                    {
                        projectEntity.Adapt(parentEntity);
                    }
                    var allChildren = _dbContext.Queryable<ProjectEntity>().ToChildList(it => it.ParentId, parentEntity.Id, false);
                    parentEntity.CostSGDAmountBeforeTax = allChildren.Sum(x => x.CostSGDAmountBeforeTax);
                    parentEntity.CostRMBAmountBeforeTax = allChildren.Sum(x => x.CostRMBAmountBeforeTax);
                    parentEntity.CostSGDAmountAfterTax = allChildren.Sum(x => x.CostSGDAmountAfterTax);
                    parentEntity.CostRMBAmountAfterTax = allChildren.Sum(x => x.CostRMBAmountAfterTax);

                    await _dbContext.Updateable<ProjectEntity>(parentEntity).UpdateColumns(x => new { x.CostSGDAmountBeforeTax, x.CostRMBAmountBeforeTax, x.CostSGDAmountAfterTax, x.CostRMBAmountAfterTax }).ExecuteCommandAsync();
                }

                #endregion 计算成本合计(编辑时)

                #region 运营成本

                if (projectDto.FormType == ProjectFormEnum.CustomerSettlement.ToString())
                {
                    List<ProjectOperateCostEntity> operateCostEntities = new List<ProjectOperateCostEntity>();
                    //银行手续费
                    operateCostEntities.Add(new ProjectOperateCostEntity
                    {
                        ProjectId = projectEntity.Id,
                        Name = "银行手续",
                        Code = "Bank",
                        Amount = 0,
                        IsDefault = true
                    });
                    //对公税额
                    operateCostEntities.Add(new ProjectOperateCostEntity
                    {
                        ProjectId = projectEntity.Id,
                        Code = "TaxRate",
                        Name = "对公税额",
                        Amount = 0,
                        IsDefault = true
                    });
                    //毛利的百分比(毛利=税后销售额-税后成本)
                    operateCostEntities.Add(new ProjectOperateCostEntity
                    {
                        ProjectId = projectEntity.Id,
                        Code = "ProfitRate",
                        Name = "公司运营",
                        Amount = 0,
                        IsDefault = true
                    });
                    await _dbContext.Insertable<ProjectOperateCostEntity>(operateCostEntities).ExecuteCommandAsync();
                }
                else
                {
                    //总成本变化时需要反向更新运营成本的最新毛利百分比
                    ProjectOperateCostEntity costEntity = await _dbContext.Queryable<ProjectOperateCostEntity>().Where(x => x.ProjectId == parentEntity.Id && x.Code == "ProfitRate").FirstAsync();
                    costEntity.Amount = (parentEntity.SaleRMBAmountAfterTax - parentEntity.CostRMBAmountAfterTax) * costEntity.Rate * 0.01m;
                    await _dbContext.Updateable<ProjectOperateCostEntity>(costEntity).UpdateColumns(x => x.Amount).ExecuteCommandAsync();
                }

                #endregion 运营成本

                await _dbContext.CommitTranAsync();

                return Json(DataResult.Success("提交成功！"));
            }
            catch (Exception ex)
            {
                await _dbContext.RollbackTranAsync();
                return Json(DataResult.Error($"{ex.Message}"));
            }
        }

        /// <summary>
        /// 编辑表单
        /// </summary>
        /// <param name="projectId"></param>
        /// <returns></returns>
        public async Task<ActionResult> SetQuotationForm(int projectId)
        {
            ProjectDto projectDto = new ProjectDto();
            try
            {
                #region 表头信息

                ProjectEntity projectEntity = await _dbContext.Queryable<ProjectEntity>().InSingleAsync(projectId);
                projectEntity.Adapt(projectDto);
                //行程分段
                projectDto.CountrySegment = projectEntity.CountrySegment.ToList<int>(',', s => int.Parse(s));
                //报价类目
                projectDto.QuotationItemCode = projectEntity.QuotationItemCode.ToList<string>(',', s => s);
                //参与人员
                projectDto.InvolveId = projectEntity.InvolveId.ToList<int?>(',', s => int.Parse(s));
                //团费新币
                projectDto.TotalSGDBeforeTax = projectEntity.SaleSGDAmountBeforeTax.ToString();
                //团费人民币
                projectDto.TotalRMBBeforeTax = projectEntity.SaleRMBAmountBeforeTax.ToString();
                //人均人民币
                projectDto.AverageRMBBeforeTax = projectEntity.AverageSaleRMBAmountBeforeTax.ToString();

                #endregion 表头信息

                #region 行程天数

                List<ProjectQuotationTripEntity> tripEntitys = await _dbContext.Queryable<ProjectQuotationTripEntity>().Where(x => x.ProjectId == projectId).ToListAsync();
                foreach (var item in tripEntitys)
                {
                    TripItem tripItem = new TripItem();
                    item.Adapt(tripItem);
                    tripItem.TripPlaceId = item.TripPlaceId.ToList<int>(',', s => int.Parse(s));
                    tripItem.TripPlaceName = item.TripPlaceName.ToList<string>(',', s => s);
                    projectDto.TripItemList.Add(tripItem);
                }

                #endregion 行程天数

                #region 行程安排

                List<ProjectQuotationItemEntity> itemEntitys = await _dbContext.Queryable<ProjectQuotationItemEntity>()
                                                                               .Includes(x => x.ItemDetail)
                                                                               .Includes(x => x.TransportDetail)
                                                                               .Includes(x => x.ActivityDetail)
                                                                               .Where(x => x.ProjectId == projectId).ToListAsync();

                foreach (var item in itemEntitys)
                {
                    QuotationItem quotationItem = new QuotationItem();
                    item.Adapt(quotationItem);
                    quotationItem.TransportDetail = item.TransportDetail.Select(x => new TransportItemDetail { Code = item.QuotationItemCode, SegmentId = item.SegmentId.ToInt(), ItemId = item.ItemId.ToInt(), Day = x.Day, UseTime = x.UseTime, PlanHour = x.PlanHour, OverTime = x.OverTime, ServiceFee = x.ServiceFee, SalaryFee = x.SalaryFee, OverTimeFee = x.OverTimeFee, TotalFee = x.TotalFee }).ToList();
                    quotationItem.ActivityDetail = item.ActivityDetail.Select(x => new ActivityItemDetail { Code = item.QuotationItemCode, SegmentId = item.SegmentId.ToInt(), ItemId = item.ItemId.ToInt(), Name = x.Name, ItemName = x.ItemName, ItemCostName = x.ItemCostName, ItemCostPrice = x.ItemCostPrice, ItemSalePrice = x.ItemSalePrice, ItemQty = x.ItemQty, Mark = x.Mark }).ToList();
                    projectDto.QuotationItemList.Add(quotationItem);
                }

                #endregion 行程安排

                #region 付款信息

                if (projectEntity.FormType == ProjectFormEnum.CustomerSettlement.ToString())
                {
                    List<ProjectPaymentEntity> payments = await _dbContext.Queryable<ProjectPaymentEntity>().Where(x => x.ProjectId == projectId).ToListAsync();
                    projectDto.PayMoneyList = payments.Select(x => new PayMoney
                    {
                        PayType = x.PaymentType,
                        PayDate = x.AmountOn,
                        PayRate = x.Ratio,
                        PaySGD = x.AmountSGD,
                        PayRMB = x.AmountRMB
                    }).ToList();
                }

                #endregion 付款信息

                return Content(DataResult<ProjectDto>.Success(projectDto).ToJson());
            }
            catch (Exception ex)
            {
                return Content(DataResult.Error($"失败:{ex.Message}").ToJson());
            }
        }

        /// <summary>
        /// 获取交通导游的成本明细项
        /// </summary>
        /// <returns></returns>
        public async Task<ActionResult> GetQuotationTransportDetail(int projectId, int itemId, string code)
        {
            List<ProjectQuotationTransportDetailEntity> transportDetailEntitys = await _dbContext.Queryable<ProjectQuotationTransportDetailEntity>()
                                                                                                 .Includes(x => x.projectQuotationItem)
                                                                                                 .Where(x => x.ProjectId == projectId && x.projectQuotationItem.QuotationItemCode == code && x.projectQuotationItem.ItemId == itemId)
                                                                                                 .OrderBy(x => x.Day)
                                                                                                 .ToListAsync();
            return Content(DataResult<List<ProjectQuotationTransportDetailEntity>>.Success(transportDetailEntitys).ToJson());
        }

        /// <summary>
        /// 提交财务等待收支
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ActionResult> SubmitFinance(int projectId)
        {
            try
            {
                await _dbContext.Updateable<ProjectEntity>().SetColumns(x =>
                new ProjectEntity()
                {
                    Status = (int)ProjectStatusEnum.WaitMoney,
                    UpdatedOn = DateTime.Now,
                    UpdatedBy = OperatorProvider.Provider.GetCurrent().Id
                })
                .Where(x => x.Id == projectId || x.ParentId == projectId).ExecuteCommandAsync();
                return Json(DataResult.Success("提交成功！"));
            }
            catch (Exception ex)
            {
                return Json(DataResult.Error($"失败,失败原因:{ex.Message}"));
            }
        }

        /// <summary>
        /// 撤销结算
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ActionResult> DeleteSettlement(int projectId)
        {
            try
            {
                await _dbContext.BeginTranAsync();
                //先删除表体相关
                var projectSettlements = await _dbContext.Queryable<ProjectEntity>().Where(x => x.ParentId == projectId).ToListAsync();
                foreach (var item in projectSettlements)
                {
                    //清空行程天数
                    await _dbContext.Deleteable<ProjectQuotationTripEntity>().Where(x => x.ProjectId == projectId || x.ProjectId == item.Id).ExecuteCommandAsync();
                    //清空行程安排和明细
                    await _dbContext.Deleteable<ProjectQuotationItemEntity>().Where(x => x.ProjectId == projectId || x.ProjectId == item.Id).ExecuteCommandAsync();
                    await _dbContext.Deleteable<ProjectQuotationItemDetailEntity>().Where(x => x.ProjectId == projectId || x.ProjectId == item.Id).ExecuteCommandAsync();
                    await _dbContext.Deleteable<ProjectQuotationTransportDetailEntity>().Where(x => x.ProjectId == projectId || x.ProjectId == item.Id).ExecuteCommandAsync();
                    await _dbContext.Deleteable<ProjectQuotationActivityDetailEntity>().Where(x => x.ProjectId == projectId || x.ProjectId == item.Id).ExecuteCommandAsync();
                    //清空付款信息
                    await _dbContext.Deleteable<ProjectPaymentEntity>().Where(x => x.ProjectId == projectId || x.ProjectId == item.Id).ExecuteCommandAsync();
                }

                //后清空表头(客户结算单和销售结算单)
                await _dbContext.Deleteable<ProjectEntity>().Where(x => x.Id == projectId || x.ParentId == projectId).ExecuteCommandAsync();

                await _dbContext.CommitTranAsync();
                return Json(DataResult.Success("撤销成功！"));
            }
            catch (Exception ex)
            {
                await _dbContext.RollbackTranAsync();
                return Json(DataResult.Error($"失败,失败原因:{ex.Message}"));
            }
        }

        /// <summary>
        /// 申请成本支付
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ActionResult> ApplyCostPay(int projectId)
        {
            try
            {
                //获取管理角色用户
                var users = await _dbContext.Queryable<UserRole>().Includes(x => x.Role).Where(x => x.Role.Code == RoleTypeEnum.Admin.ToString()).ToListAsync();
                ProjectEntity projectEntity = await _dbContext.Queryable<ProjectEntity>().InSingleAsync(projectId);
                projectEntity.PayStatus = (int)ProjectCostPayEnum.PayAudit;
                projectEntity.PayAuditId = string.Join(",", users.Select(x => x.UserId).ToArray());
                projectEntity.UpdatedOn = projectEntity.PayApplyOn = DateTime.Now;
                projectEntity.UpdatedBy = OperatorProvider.Provider.GetCurrent().Id;
                await _dbContext.Updateable(projectEntity).UpdateColumns(x => new { x.PayStatus, x.PayAuditId, x.PayApplyOn, x.UpdatedOn, x.UpdatedBy }).ExecuteCommandAsync();
                return Json(DataResult.Success("申请成功！"));
            }
            catch (Exception ex)
            {
                return Json(DataResult.Error($"失败,失败原因:{ex.Message}"));
            }
        }

        /// <summary>
        /// 获取团组看板视图明细(>=当天)
        /// </summary>
        /// <returns></returns>
        public async Task<ActionResult> GetDashBoardDetail()
        {
            try
            {
                var tripPreAlarmDay = CacheHelper.GetCache("TripPreAlarmDay").ToInt();
                List<DashBoardViewDto> datas = await _dbContext.Queryable<ProjectEntity>()
                                                           .Where(x => x.FormType == ProjectFormEnum.CustomerSettlement.ToString() && x.DepartureDate >= DateTime.Now.Date)
                                                           //.Where(x => x.Status == (int)ProjectStatusEnum.DataIn)
                                                           .WhereIF(OperatorProvider.Provider.GetCurrent().DataScope == (int)DataScopeEnum.SELF, x => x.SaleManagerId == OperatorProvider.Provider.GetCurrent().Id)
                                                           .OrderBy(x => x.DepartureDate)
                                                           .Select(x => new DashBoardViewDto
                                                           {
                                                               Id = x.Id,
                                                               DepartureDate = x.DepartureDate,
                                                               ReturnDate = x.ReturnDate,
                                                               Name = x.Name,
                                                               CustomerName = x.CustomerName,
                                                               GroupInfo = $"{x.AdultTotal}成人/{x.ChildTotal}儿童/{x.TeamLeader}领队",
                                                               SaleManagerName = x.SaleManagerName,
                                                               TripPreAlarmDay = tripPreAlarmDay,
                                                               Color = x.Color
                                                           }).ToListAsync();
                return Content(DataResult<List<DashBoardViewDto>>.Success(datas).ToJson());
            }
            catch (Exception ex)
            {
                return Content(DataResult<object>.Error($"获取失败,{ex.Message}").ToJson());
            }
        }

        #region 公共方法

        /// <summary>
        /// 生成自定义项目编号
        /// </summary>
        /// <param name="tripStartDate"></param>
        /// <returns></returns>
        public string GetNumberCode(DateTime tripStartDate)
        {
            //查询相同出行日期的最新编号
            string defectItemCode = _dbContext.Queryable<ProjectEntity>().Where(x => x.FormType == ProjectFormEnum.CustomerSettlement.ToString() && x.DepartureDate == tripStartDate && x.Code.Length > 8)
                                             .OrderByDescending(x => x.Code)
                                             .Select(s => s.Code)
                                             .First();
            NumberRule numberRule = _dbContext.Queryable<NumberRule>()
                                              .Where(x => x.FormCode == "ProjectForm")
                                              .First();
            string rule = numberRule.Prefix + tripStartDate.ToString(EnumHelper.ConvertEnumToString<NumberRuleEnum>(numberRule.CodeRule));
            if (string.IsNullOrEmpty(defectItemCode))
            {
                rule += "1".PadLeft(numberRule.SerialNumber, '0');
            }
            else
            {
                rule += (defectItemCode.Substring(defectItemCode.Length - numberRule.SerialNumber).ToInt() + 1).ToString("0".PadLeft(numberRule.SerialNumber, '0'));
            }
            return rule;
        }

        #endregion 公共方法
    }
}